#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <signal.h> 
#include <sys/types.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyUSB0"
#define _POSIX_SOURCE 1 /* POSIX 系统兼容 */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE; 

void signal_handler_IO (int status);   /* 定义信号处理程序 */
int wait_flag=TRUE;                    /* 没收到信号的话就会是 TRUE */

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  struct sigaction saio;           /* definition of signal action */
  char buf[255];

  /* 开启装置为 non-blocking (读取功能会马上结束返回) */
  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
  if(fd <0)
  {
	perror(MODEMDEVICE);
	exit(-1);
  }

  /* 在使装置非同步化前, 安装信号处理程序 */
  saio.sa_handler = signal_handler_IO;
  sigemptyset(&saio.sa_mask);//saio.sa_mask=0;必须用sigemptyset函数初始化的act结构的sa_mask成员  /*saio.sa_mask = 0; 清空信号集*/
  //saio.sa_mask = 0;
  saio.sa_flags = 0;
  saio.sa_restorer = NULL;
  sigaction(SIGIO,&saio,NULL);
  
  /* 允许行程去接收 SIGIO 信号*/
  fcntl(fd, F_SETOWN, getpid());
  /* 使文档ake the file descriptor 非同步 (使用手册上说只有 O_APPEND 及
  O_NONBLOCK, 而 F_SETFL 也可以用...) */
  fcntl(fd, F_SETFL, FASYNC);

  tcgetattr(fd,&oldtio); /* 储存目前的序列埠设定值 */
  /* 设定新的序列埠为标准输入程序 */
  newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
  //newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR | ICRNL;
  newtio.c_oflag = 0;
  //newtio.c_lflag = ICANON;
  newtio.c_lflag = ~ICANON;
  newtio.c_cc[VMIN]=3;//1
  newtio.c_cc[VTIME]=0;
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);

  /* 等待输入信号的回圈. 很多有用的事我们将在这做 */
  memset(buf,0,sizeof(buf)); 
  while (STOP==FALSE) 
  {
    printf(".\n");
    usleep(100000);
    /* 在收到 SIGIO 后, wait_flag = FALSE, 输入信号存在则可以被读取 */
    if (wait_flag==FALSE) 
    { 
/*************************************
      res = read(fd,buf,255);
      buf[res]=0;
      printf(":%s:%d\n", buf, res);
**************************************/
      //memset(buf,0,sizeof(buf));
      res=read(fd,buf,256);
      //printf ("nread=%d,%s\n", res, buf);
      if (res==3)
      { 
	printf ("nread=%d,%s\n", res, buf);	
	memset(buf,0,sizeof(buf));         
	STOP=TRUE; /* 如果只输入 CR 则停止回圈 */
      }
      wait_flag = TRUE;      /* 等待新的输入信号 */
    }
  }
  /* 回存旧的序列埠设定值 */
  tcsetattr(fd,TCSANOW,&oldtio);
}

/***************************************************************************
* 信号处理程序. 设定 wait_flag 为 FALSE, 以使上述的回圈能接收字元          *
***************************************************************************/

void signal_handler_IO (int status)
{
  printf("received SIGIO signal.\n");
  wait_flag = FALSE;
}
